package com.card.server.utils;

import com.card.server.config.RedisService;
import com.card.server.domain.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import reactor.core.publisher.FluxSink;

import java.util.*;

/**
 * @author TISNIW
 * @version 1.0
 * @date 2025/6/2 21:09
 * @desc
 */
@Component
public class GameUtil {
    private static final Logger log = LoggerFactory.getLogger(GameUtil.class);
    @Autowired
    private RedisService redisService;
    @Autowired
    private DeckUtil deckUtil;
    public void check(){
        // 1. 获取所有房间中信息
        for (int game = 1; game <= 1; game++) { // 示例只支持 game=1（斗地主）
            for (int table = 1; table <= 4; table++) {
                String poolKey = game + ":" + table + ":";
                Set<String> keys = redisService.getKeysByPattern(poolKey + "*");
                if (keys != null && !keys.isEmpty()) {
                    for (String key : keys) {
                        Room room = redisService.getCacheObject(key, Room.class);
                        if (room.getStatus() == 1) {
                            //key的格式game:table:roomKey
                            //获取roomKey
                            String roomKey = key.substring(key.lastIndexOf(":") + 1);

                            checkGame(roomKey);
                        }
                    }
                }
            }
        }



    }

    private void checkGame(String roomKey) {
        String gameKey = "game:"+ roomKey + ":";
        GameInfo gameInfo = redisService.getCacheObject(gameKey, GameInfo.class);
        List<Integer> playerId = new ArrayList<>();

        Map<String, Object> response = new HashMap<>();
        for(int i = 0;i<gameInfo.getPlayers().size();i++){
            if (gameInfo.getPlayers().get(i).getId() > 0){
                if (gameInfo.getPlayers().get(i).getCards() != null){
                    List<Player> reorderedList = new ArrayList<>();
                    // 添加从 index 到末尾的部分
                    reorderedList.addAll(gameInfo.getPlayers().subList(i, gameInfo.getPlayers().size()));
                    // 再添加从开头到 index 前一个元素的部分
                    reorderedList.addAll(gameInfo.getPlayers().subList(0, i));
                    List<Card> cards = gameInfo.getPlayers().get(0).getCards();
                    Collections.sort(cards);
                    response.put("cards",cards);
                    response.put("opponent1Cards",gameInfo.getPlayers().get(1).getCards().size());
                    response.put("opponent2Cards",gameInfo.getPlayers().get(2).getCards().size());
                }
                playerId.add(gameInfo.getPlayers().get(i).getId());
            }

        }
        response.put("status", gameInfo.getStatus());
        switch (gameInfo.getStatus()) {
            case 1:
                gameInfo.setStatus(2);
                log.info ("游戏变更为状态:{}",gameInfo.getStatus());
                response.put("message", "所有玩家已经进入游戏，游戏准备发牌");
                break;
            case 2:
                log.info("开始发牌");
                List<List<Card>> groups = deckUtil.splitDeckToGroups();
                for (int i = 0; i < gameInfo.getPlayers().size(); i++) {
                    Player player = gameInfo.getPlayers().get(i);
                    player.setCards(groups.get(i));
                }
                int n = findCardGroup(groups, "hearts", "4");
                if (n == 3) {
                    n = 0;
                }
                gameInfo.setCurrentPlayer(n);
                gameInfo.setLastPlayer((gameInfo.getCurrentPlayer()-1) %3);
                gameInfo.setNextPlayer((gameInfo.getCurrentPlayer()+1)%3);
                gameInfo.setBottomCards(groups.get(groups.size() - 1));
                gameInfo.setStatus(3);
                log.info ("游戏变更为状态:{}",gameInfo.getStatus());
                response.put("message", "发牌中");
                break;
            case 3:
                gameInfo = callLandlord(gameInfo,roomKey);
                //gameInfo.setStatus(4);
                //log.info ("游戏变更为状态:{}",gameInfo.getStatus());
                response.put("message", "叫地主");
                break;
            case 4:
                response.put("message", "抢地主");
                break;
            case 5:
                sendPlayerMessage(gameInfo,roomKey);
                gameInfo = sendPlayer(gameInfo,roomKey);
                response.put("message", "出牌");
                break;
            case 6:
                response.put("message", "结算");
                break;
        }

        response.put("gameKey", gameKey);
        response.put("timestamp", System.currentTimeMillis());
        redisService.setCacheObject(gameKey, gameInfo);
        for (int id : playerId) {
            String gameCode = id + "_" + roomKey;
            FluxSink<String> emitter =  GameEmitters.gameEmitters.get(gameCode);
            if(emitter != null){
                emitter.next(JsonUtils.writeValueAsString(response));
            }
        }
    }

    private GameInfo sendPlayer(GameInfo gameInfo, String roomKey) {
        Map<String, Object> response = new HashMap<>();
        response.put("message", "等待出牌");
        response.put("code", 14); // 进入游戏阶段
        response.put("landlordIndex", gameInfo.getLandlordPlayer());
        response.put("bottomCards",gameInfo.getBottomCards());
        for (int i = 0; i < gameInfo.getPlayers().size(); i++) {
            Player player = gameInfo.getPlayers().get(i);
            if (player.getId() > 0) {
                response.put("index", i);
                String gameCode = player.getId() + "_" + roomKey;
                FluxSink<String> emitter = GameEmitters.playEmitters.get(gameCode);

                if (emitter != null) {
                    emitter.next(JsonUtils.writeValueAsString(response));
                }
            }
        }
        int currentPlayerIndex = gameInfo.getCurrentPlayer();
        if (currentPlayerIndex < 0) {

        }
        List<Player> players = gameInfo.getPlayers();

        // 构造通用消息（给其他玩家）
        Map<String, Object> othersMessage = new HashMap<>();
        othersMessage.put("code", 1); // 表示正在等待别人出牌
        othersMessage.put("currentPlayerId", currentPlayerIndex);
        othersMessage.put("landlordIndex", gameInfo.getLandlordPlayer());
        othersMessage.put("endTime", 30); // 出牌倒计时
        othersMessage.put("message", "等待其他玩家出牌");

        Map<String, Object> currentMessage = new HashMap<>();
        currentMessage.put("code", 5); // 表示轮到你出牌
        currentMessage.put("message", "轮到你出牌");
        currentMessage.put("landlordIndex", gameInfo.getLandlordPlayer());
        currentMessage.put("endTime", 30);

        // 遍历所有玩家，分别发送不同消息
        for (int i = 0; i < players.size(); i++) {
            Player player = players.get(i);
            if (player.getId() < 0) continue; // 忽略 AI

            String gameCode = player.getId() + "_" + roomKey;
            FluxSink<String> emitter = GameEmitters.playEmitters.get(gameCode);

            if (emitter != null) {
                try {
                    if (i == currentPlayerIndex) {
                        // 当前操作玩家：发送 code=5
                        currentMessage.put("index", i);
                        emitter.next(JsonUtils.writeValueAsString(currentMessage));
                    } else {
                        // 其他玩家：发送 code=1
                        othersMessage.put("index", i);
                        emitter.next(JsonUtils.writeValueAsString(othersMessage));
                    }
                } catch (Exception e) {
                    log.error("发送消息失败: {}", e.getMessage());
                }
            }
        }
        gameInfo.setEndTime(30L); // 设置倒计时
        redisService.setCacheObject("game:" + roomKey + ":", gameInfo);

        return gameInfo;
    }

    private GameInfo callLandlord(GameInfo gameInfo, String gameKey) {
        int currentPlayerIndex = gameInfo.getCurrentPlayer();
        Player currentPlayer = gameInfo.getPlayers().get(currentPlayerIndex);
        // 构建两种不同的响应消息
        Map<String, Object> messageForCurrent = new HashMap<>();
        Map<String, Object> messageForOthers = new HashMap<>();
        Map<String, Object> messageForAIs = new HashMap<>();
        // 如果是 AI 玩家（id < 0），只处理倒计时和自动切换
        if (currentPlayer.getId() < 0) {
            if (gameInfo.getEndTime() == null) {
                gameInfo.setEndTime(30L);
            }

            long newTime = gameInfo.getEndTime() - 1;
            gameInfo.setEndTime(newTime);

            if (newTime <= 15) {
                int nextPlayerIndex = (currentPlayerIndex + 1) % 3;
                gameInfo.setCurrentPlayer(nextPlayerIndex);
                gameInfo.setLastPlayer((nextPlayerIndex - 1 + 3) % 3);
                gameInfo.setNextPlayer((nextPlayerIndex + 1) % 3);
                gameInfo.setEndTime(30L);
                messageForAIs.put("code",12);
                messageForAIs.put("message", false);
            }
            messageForOthers.put("code", 1);
            messageForOthers.put("currentPlayerId", currentPlayerIndex);
            messageForOthers.put("endTime", gameInfo.getEndTime());
        } else {
            // 真实玩家，处理倒计时，并通知其他玩家
            if (gameInfo.getEndTime() == null) {
                gameInfo.setEndTime(30L);
            }

            long newTime = gameInfo.getEndTime() - 1;
            gameInfo.setEndTime(newTime);

            if (newTime <= 0) {
                int nextPlayerIndex = (currentPlayerIndex + 1) % 3;
                gameInfo.setCurrentPlayer(nextPlayerIndex);
                gameInfo.setLastPlayer((nextPlayerIndex - 1 + 3) % 3);
                gameInfo.setNextPlayer((nextPlayerIndex + 1) % 3);
                gameInfo.setEndTime(30L);
            }


            messageForCurrent.put("code", 2);
            messageForCurrent.put("endTime", gameInfo.getEndTime());


            messageForOthers.put("code", 1);
            messageForOthers.put("currentPlayerId", currentPlayerIndex);
            messageForOthers.put("endTime", gameInfo.getEndTime());

            // 广播消息给所有非 AI 用户

        }
        broadcastMessages(gameInfo, gameKey, currentPlayer.getId(), messageForCurrent, messageForOthers, messageForAIs);
        return gameInfo;
    }
    public static int findCardGroup(List<List<Card>> groups, String targetDecor, String targetNumber) {
        for (int i = 0; i < groups.size(); i++) {
            List<Card> group = groups.get(i);
            for (int j = 0; j < group.size(); j++) {
                Card card = group.get(j);
                if (targetDecor.equals(card.getDecor()) && targetNumber.equals(card.getNumber())) {
                    return i;
                }
            }
        }
        return 0;
    }
    private void broadcastMessages(
            GameInfo gameInfo,
            String gameKey,
            int currentUserId,
            Map<String, Object> messageForCurrent,
            Map<String, Object> messageForOthers,
            Map<String, Object> messageForAIs
    ) {
        List<Player> players = gameInfo.getPlayers();


        for (int i  = 0; i < players.size(); i++) {
            if (players.get(i).getId() < 0) {
                // 忽略 AI 玩家
                continue;
            }

            String gameCode = players.get(i).getId() + "_" + gameKey;
            FluxSink<String> emitter = GameEmitters.playEmitters.get(gameCode);

            if (emitter != null) {
                try {
                    if (players.get(i).getId() == currentUserId) {
                        String jsonMessage = JsonUtils.writeValueAsString(messageForCurrent);
                        emitter.next(jsonMessage);
                    } else {
                        messageForOthers.put("index", i);
                        String jsonMessage = JsonUtils.writeValueAsString(messageForOthers);
                        emitter.next(jsonMessage);
                        if (messageForAIs.size() > 0){
                            String jsonMessageForAI = JsonUtils.writeValueAsString(messageForAIs);
                            emitter.next(jsonMessageForAI);
                        }
                    }
                } catch (Exception e) {
                    log.info("❌ 发送给玩家 [" + players.get(i).getId() + "] 失败：");
                    e.printStackTrace();
                }
            } else {
                log.warn("⚠️ 玩家 [" + players.get(i).getId() + "] 的连接不存在，无法发送消息。");
            }
        }
    }

    public void sendPlayerMessage(GameInfo gameInfo, String room) {
        //更新卡牌信息数据
        Map<String, Object> message = new HashMap<>();
        message.put("code", 10);
        for(int i = 0;i<gameInfo.getPlayers().size();i++){
            if (gameInfo.getPlayers().get(i).getId() > 0){
                if (gameInfo.getPlayers().get(i).getCards() != null){
                    List<Player> reorderedList = new ArrayList<>();
                    // 添加从 index 到末尾的部分
                    reorderedList.addAll(gameInfo.getPlayers().subList(i, gameInfo.getPlayers().size()));
                    // 再添加从开头到 index 前一个元素的部分
                    reorderedList.addAll(gameInfo.getPlayers().subList(0, i));
                    List<Card> cards = gameInfo.getPlayers().get(0).getCards();
                    Collections.sort(cards);
                    message.put("cards",cards);
                    message.put("opponent1Cards",gameInfo.getPlayers().get(1).getCards().size());
                    message.put("opponent2Cards",gameInfo.getPlayers().get(2).getCards().size());
                    message.put("bottomCards",  gameInfo.getBottomCards());
                }
                String gameCode = gameInfo.getPlayers().get(i).getId() + "_" + room;
                FluxSink<String> emitter = GameEmitters.playEmitters.get(gameCode);
                if (emitter != null) {
                    try {
                        emitter.next(JsonUtils.writeValueAsString(message));
                    } catch (Exception e) {
                        log.error("SSE 推送失败: {}", e.getMessage());
                    }
                }
            }

        }
    }
}
